package a202110.day13;

/**
 * 反转字符串
 * <p>
 * 编写一个函数，其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
 * <p>
 * 不要给另外的数组分配额外的空间，你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
 * <p>
 * 输入：s = ["h","e","l","l","o"]
 * 输出：["o","l","l","e","h"]
 * <p>
 * 输入：s = ["H","a","n","n","a","h"]
 * 输出：["h","a","n","n","a","H"]
 * <p>
 * 提示:
 * 1 <= s.length <= 105
 * s[i] 都是 ASCII 码表中的可打印字符
 *
 * @author yousj
 * @since 2021/10/31
 */
public class Main {

    public static void main(String[] args) {
        char[] chars = "xsfadsfe".toCharArray();
        reverseString1(chars);
        System.out.println(chars);
    }

    private static void reverseString(char[] s) {
        int len = s.length;
        for (int i = 0; i < len >> 1; i++) {
            char tmp = s[len - 1 - i];
            s[len - 1 - i] = s[i];
            s[i] = tmp;
        }
    }

    /**
     * java中的 |=、&=、^=
     * <p>
     * 关于 |= 运算符：|= 运算符和 += 这一类的运算符一样，拆解开就是 a = a | b；
     * int a = 5;  // 0000 0101
     * int b = 3;  // 0000 0011
     * a |= b;     // 0000 00111
     * 具体规则为：两个二进制对应位为0时该位为0，否则为1。
     * 拿5的二进制 0000 0101 和 3的二进制 0000 0011 进行|运算，
     * 后三位的的对应位都不是同时等于0，所以最终结果为 0000 0111 也就是7的二进制。
     * <p>
     * 关于 &= 运算符：
     * int a = 5;  // 0000 0101
     * int b = 3;  // 0000 0011
     * a &= b;     // 0000 0001
     * 具体规则为：两个二进制对应位都为1时，结果为1，否则结果为都0。
     * 拿5的二进制 0000 0101 和 3的二进制 0000 0011 进行&运算，
     * 只有最后一位都为1，则最终结果为 0000 0001 也就是1的二进制。
     * <p>
     * 关于 ^= 运算符：
     * int a = 5;  // 0000 0101
     * int b = 3;  // 0000 0011
     * a ^= b;     // 0000 0110
     * 具体规则为：两个二进制对应位相同时，结果为0，否则结果为1。
     * 拿5的二进制 0000 0101 和 3的二进制 0000 0011 进行^运算，1-5位对应位都是0所以1-5位都为0，
     * 第8位都为1所以第8位也为0，其他的对应位都不相等所以为1，则最终结果为 0000 0110 也就是6的二进制。
     * <p>
     * 总结：
     * <p>
     * |=：两个二进制对应位都为0时，结果等于0，否则结果等于1；
     * <p>
     * &=：两个二进制的对应位都为1时，结果为1，否则结果等于0；
     * <p>
     * ^=：两个二进制的对应位相同，结果为0，否则结果为1。
     * <p>
     * 位运算描述:
     * 符号	    描述	        运算规则
     * &	    与	        两个位都为1时，结果才为1
     * |	    或	        两个位都为0时，结果才为0
     * ^	    异或	        两个位相同为0，相异为
     * ~	    取反	        0变1，1变0
     * <<	    左移	        各二进位
     * <<<      无符号左移    忽略符号位，空位都以0补齐
     * >>	    右移	        各二进位全部右移若干位，对无符号数，高位补0，有符号数，各编译器处理方法不一样，有的补符号位（算术右移），有的补0（逻辑右移）
     * >>>      无符号右移    忽略符号位，空位都以0补齐
     */
    private static void reverseString1(char[] s) {
        int len = s.length;
        for (int i = 0; i < len >> 1; ++i) {
            int j = len - 1 - i;
            s[i] ^= s[j];
            s[j] ^= s[i];
            s[i] ^= s[j];
        }
    }

}
